<?php
require_once dirname(__FILE__) . '/../../bootstrap.unit.php';
require_once FORAGE_APP_PATH . '/behaviours/test/TestBehaviour.php';
require_once FORAGE_APP_PATH . '/behaviours/test/TestBehaviours.php';

class ForageQueryTest extends ForageUnitTestCase
{
  private $query;

  public function setUp()
  {
    $this->query = new ForageQuery();
  }

  public function tearDown()
  {
    unset($this->query);
  }

  public function testDefaultQueryObject()
  {
    $this->assertNull($this->query->query_string);
    $this->assertEquals(10, $this->query->per_page);
    $this->assertEquals(1, $this->query->page);
  }

  public function testAlteringQueryString()
  {
    $this->query->setQueryString("new query string");
    $this->assertEquals('new query string', $this->query->query_string);
  }

  public function testAlteringPerPageValue()
  {
    $this->query->setPerPage(5);
    $this->assertEquals(5, $this->query->per_page, 'Per page value should have been altered.');
  }

  /**
   * @expectedException InvalidArgumentException
   */
  public function testAlteringPerPageValueFailsWithNonInteger()
  {
    $this->query->setPerPage('blah');
  }

  public function testAlteringPageValue()
  {
    $this->query->setPage(5);
    $this->assertEquals(5, $this->query->page, 'Page value should have been altered.');
  }

  /**
   * @expectedException InvalidArgumentException
   */
  public function testAlteringPageValueFailsWithNonInteger()
  {
    $this->query->setPage('blah');
  }

  public function testCalculatedDocumentIndexValues()
  {
    $this->assertEquals(0, $this->query->start_index, 'Default start index should be 0.');
    $this->assertEquals(10, $this->query->end_index, 'Default end index should be 10.');
    
    $this->query->setPage(3);
    $this->query->setPerPage(3);

    $this->assertEquals(6, $this->query->start_index, 'Start index of page 3 of 3 items per page should be 6.');
    $this->assertEquals(9, $this->query->end_index, 'End index of page 3 of 3 items per page should be 12.');
  }

  public function testAddingBehaviours()
  {
    $query = new ForageQuery();
    try {
      $query->behaviourTest();
      $this->fail('Behaviour method should throw exception before being added.');
    } catch (BadMethodCallException $e) {}
    $query->addBehaviour(new ForageTestQueryBehaviour());
    $this->assertTrue($query->behaviourTest());
  }

  public function testCheckingForBehaviours()
  {
    $query = new ForageQuery();
    $this->assertFalse($query->hasBehaviour('ForageTestQueryBehaviour'));
    $query->addBehaviour(new ForageTestQueryBehaviour());
    $this->assertTrue($query->hasBehaviour('ForageTestQueryBehaviour'));
  }

  /**
   * @expectedException InvalidArgumentException
   */
  public function testNonQueryBehaviourCannotBeAdded()
  {
    $query = new ForageQuery();
    $query->addBehaviour(new ForageTestBehaviour());
  }

  public function testAddingASortField()
  {
    $query = new ForageQuery();
    $query->addSortField('title', SORT_ASC);
    $sort_fields = $query->sort_fields;
    $this->assertEquals(1, count($sort_fields));
    $this->assertEquals(array('title'=>SORT_ASC), $sort_fields);
  }

  /**
   * @expectedException InvalidArgumentException
   */
  public function testAddingASortFieldFailsWithBadSortDirection()
  {
    $query = new ForageQuery();
    $query->addSortField('title', 'foo');
  }
}
